#!/usr/bin/env python3
#
#  Copyright 2016 The TMM/AD Authors. All rights reserved.
#  Use of this source code is governed by a BSD-style license that can be
#  found in the license.txt file.
#

import tmm.web.base.ansi as _ansi
import tmm.web.base.file_lock as _file_lock
import tmm.web.base.terminal as _terminal
import datetime as _datetime


#  Log levels.
class LogLevel:
    """Log levels."""

    INFORMATION = 0
    WARNING = 1
    ERROR = 2


def log_message(message, level=LogLevel.INFORMATION, write_file=None):
    """Log a message.

    :type message: str
    :type level: int
    :type write_file: str | None
    :param message: The message.
    :param level: The error level.
    :param write_file: The file name of the log. (Set to None if there is no such file.)
    """

    #  Build the origin message.
    msg = "[%s][%s] %s" % (
        {
            LogLevel.INFORMATION: "INFO",
            LogLevel.WARNING: "WARN",
            LogLevel.ERROR: "ERROR"
        }[level],
        _datetime.datetime.now().strftime("D%y-%m-%d|T%H:%M:%S"),
        message
    )

    #  Build the colored message.
    if level == LogLevel.INFORMATION:
        colored_msg = _ansi.format_text(
            msg,
            fore_color=_ansi.Color.GREEN
        )
    elif level == LogLevel.WARNING:
        colored_msg = _ansi.format_text(
            msg,
            style=_ansi.Style.BOLD | _ansi.Style.UNDERLINE,
            fore_color=_ansi.Color.YELLOW
        )
    elif level == LogLevel.ERROR:
        colored_msg = _ansi.format_text(
            msg,
            style=_ansi.Style.BOLD | _ansi.Style.UNDERLINE,
            fore_color=_ansi.Color.RED,
            back_color=_ansi.Color.YELLOW
        )
    else:
        raise ValueError("Invalid level.")

    #  Show the colored message on the terminal.
    _terminal.terminal_print(colored_msg, True)

    #  Write message to file.
    if write_file is not None:
        #  Lock file.
        _file_lock.lock_file(write_file)

        fd = None
        try:
            #  Write file.
            fd = open(write_file, "a")
            fd.write(msg)
            fd.write("\n")
            fd.close()
        except IOError:
            #  Show an error message on the terminal.
            log_message(
                "I/O fault when writing log to disk.",
                level=LogLevel.ERROR,
                write_file=None
            )

            #  Close the file if possible.
            if fd is not None and not fd.closed:
                fd.close()

        #  Unlock file.
        _file_lock.unlock_file(write_file)
